package com.ideaaedi.springcloud.jd.message.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.entity.message.po.MsgExecLogPO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.req.MsgExecLogAddReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.req.MsgExecLogBatchAddReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.req.MsgExecLogListReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.req.MsgExecLogUpdateReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.resp.MsgExecLogBatchAddRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.resp.MsgExecLogDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.message.vo.resp.MsgExecLogListRespVO;
import com.ideaaedi.springcloud.jd.commonspring.mybatisplus.ServiceImplExt;
import com.ideaaedi.springcloud.jd.message.mapper.MsgExecLogMapper;
import com.ideaaedi.springcloud.jd.message.service.MsgExecLogService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 消息-执行日志 服务实现类
 * </p>
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.5.B
 */
@Service
public class MsgExecLogServiceImpl extends ServiceImplExt<MsgExecLogMapper, MsgExecLogPO> implements MsgExecLogService {

    @Nullable
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MsgExecLogDetailRespVO add(MsgExecLogAddReqVO req, boolean queryDetail) {
        MsgExecLogPO po = new MsgExecLogPO();
        BeanUtils.copyProperties(req, po);
        long id = IdWorker.getId();
        po.setId(id);
        save(po);
        return queryDetail ? detail(id) : null;
    }

    @Override
    public MsgExecLogBatchAddRespVO batchAdd(MsgExecLogBatchAddReqVO req) {
        Boolean ifOneByOne = req.getIfOneByOne();
        Objects.requireNonNull(ifOneByOne, "ifOneByOne cannot be null.");
        List<MsgExecLogBatchAddReqVO.AddItemParamDTO> dataList = req.getDataList();
        MsgExecLogService thisService = (MsgExecLogService) AopContext.currentProxy();
        if (ifOneByOne) {
            for (MsgExecLogBatchAddReqVO.AddItemParamDTO item : dataList) {
                try {
                    thisService.add(item, false);
                    item.setResult(true);
                } catch (Exception e) {
                    item.setResult(false);
                    item.setFailInfo(e.getMessage());
                }
            }
        } else {
            // 出于性能及业务差异考虑, 这里不直接生成. 需要的话，请自己实现
            throw new UnsupportedOperationException("Un-support ifOneByOne is false.");
        }
        MsgExecLogBatchAddRespVO resp = new MsgExecLogBatchAddRespVO();
        resp.setDataList(dataList);
        resp.setIfAllSuccess(dataList.stream().allMatch(x -> x.getResult() != null && x.getResult()));
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MsgExecLogDetailRespVO delete(Long id) {
        Objects.requireNonNull(id, "id cannot be null.");
        MsgExecLogDetailRespVO resp = detail(id);
        removeById(id);
        return resp;
    }

    @Nullable
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MsgExecLogDetailRespVO update(MsgExecLogUpdateReqVO req) {
        Long id = req.getId();
        Objects.requireNonNull(id, "id cannot be null.");
        // mybatis-plus默认的updateById方法，更新策略默认是NOT_NULL（即更新数据时数据为NULL值时将不更新进数据库）
        MsgExecLogPO po = new MsgExecLogPO();
        BeanUtils.copyProperties(req, po);
        updateById(po);
        return detail(id);
    }

    @Nullable
    @Override
    public MsgExecLogDetailRespVO detail(Long id) {
        Objects.requireNonNull(id, "id cannot be null.");
        MsgExecLogPO po = getById(id);
        if (po == null) {
            return null;
        }
        MsgExecLogDetailRespVO resp = new MsgExecLogDetailRespVO();
        BeanUtils.copyProperties(po, resp);
        return resp;
    }
    
    @Override
    public PageInfo<MsgExecLogListRespVO> list(MsgExecLogListReqVO req) {
        int pageNum = req.getPageNum();
        int pageSize = req.getPageSize();
        Long id = req.getId();
        String tenant = req.getTenant();
        String yyyyMmDd = req.getYyyyMmDd();
        Long msgId = req.getMsgId();
        LocalDateTime expectExecTime = req.getExpectExecTime();
        LocalDateTime actualExecTime = req.getActualExecTime();
        Integer consumeTime = req.getConsumeTime();
        Integer execIfSuccess = req.getExecIfSuccess();
        String execResult = req.getExecResult();
        Integer deleted = req.getDeleted();
        Long createdBy = req.getCreatedBy();
        LocalDateTime createdAt = req.getCreatedAt();
        Long updatedBy = req.getUpdatedBy();
        LocalDateTime updatedAt = req.getUpdatedAt();

        // 分页查
        IPage<MsgExecLogPO> pageInfo = new Page<>(pageNum, pageSize);
        IPage<MsgExecLogPO> page = this.baseMapper.selectPage(pageInfo,
                new LambdaQueryWrapper<MsgExecLogPO>()
            .eq(id != null,  MsgExecLogPO::getId, id)
            .eq(tenant != null && tenant.trim().length() != 0,  MsgExecLogPO::getTenant, tenant)
            .eq(yyyyMmDd != null && yyyyMmDd.trim().length() != 0,  MsgExecLogPO::getYyyyMmDd, yyyyMmDd)
            .eq(msgId != null,  MsgExecLogPO::getMsgId, msgId)
            .eq(expectExecTime != null,  MsgExecLogPO::getExpectExecTime, expectExecTime)
            .eq(actualExecTime != null,  MsgExecLogPO::getActualExecTime, actualExecTime)
            .eq(consumeTime != null,  MsgExecLogPO::getConsumeTime, consumeTime)
            .eq(execIfSuccess != null,  MsgExecLogPO::getExecIfSuccess, execIfSuccess)
            .eq(execResult != null && execResult.trim().length() != 0,  MsgExecLogPO::getExecResult, execResult)
            .eq(deleted != null,  MsgExecLogPO::getDeleted, deleted)
            .eq(createdBy != null,  MsgExecLogPO::getCreatedBy, createdBy)
            .eq(createdAt != null,  MsgExecLogPO::getCreatedAt, createdAt)
            .eq(updatedBy != null,  MsgExecLogPO::getUpdatedBy, updatedBy)
            .eq(updatedAt != null,  MsgExecLogPO::getUpdatedAt, updatedAt)
            .orderByDesc(MsgExecLogPO::getId)
        );
        // 转换为resp模型
        List<MsgExecLogPO> records = page.getRecords();
        List<MsgExecLogListRespVO> list;
        if (CollectionUtils.isEmpty(records)) {
            list = Collections.emptyList();
        } else {
            list = records.stream().map(po -> {
                MsgExecLogListRespVO resp = new MsgExecLogListRespVO();
                BeanUtils.copyProperties(po, resp);
                return resp;
            }).collect(Collectors.toList());
        }
        return PageInfo.of(page.getTotal(), pageNum, pageSize, list);
    }
}
